home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / tde31.zip / MACRO.C < prev    next >
C/C++ Source or Header  |  1993-08-29  |  26KB  |  740 lines

  1. /*
  2.  * The "macro" routines in TDE are not really macro routines in the classical
  3.  * sense.  In TDE, "macros" are just recordings of key sequences.  But,
  4.  * actually, I find the ability to record and playback keystrokes generally
  5.  * more useful than writing a macro.  Being that I'm so stupid, it takes me
  6.  * half the morning to write and half the afternoon to debug a simple classical
  7.  * macro.  For most of my routine, little jobs, I find it more convenient
  8.  * to record my keystrokes and playback those keystrokes at appropriate places
  9.  * in a file.  It just seems easier for me to "teach" the editor what to do
  10.  * rather than "instruct" the editor what to do.
  11.  *
  12.  * New editor name:  TDE, the Thomson-Davis Editor.
  13.  * Author:           Frank Davis
  14.  * Date:             June 5, 1991, version 1.0
  15.  * Date:             July 29, 1991, version 1.1
  16.  * Date:             October 5, 1991, version 1.2
  17.  * Date:             January 20, 1992, version 1.3
  18.  * Date:             February 17, 1992, version 1.4
  19.  * Date:             April 1, 1992, version 1.5
  20.  * Date:             June 5, 1992, version 2.0
  21.  * Date:             October 31, 1992, version 2.1
  22.  * Date:             April 1, 1993, version 2.2
  23.  * Date:             June 5, 1993, version 3.0
  24.  * Date:             August 29, 1993, version 3.1
  25.  *
  26.  * This modification of Douglas Thomson's code is released into the
  27.  * public domain, Frank Davis.  You may distribute it freely.
  28.  */
  29.  
  30.  
  31. #include "tdestr.h"             /* tde types */
  32. #include "common.h"
  33. #include "define.h"
  34. #include "tdefunc.h"
  35.  
  36.  
  37. /*
  38.  *              keystroke record functions
  39.  */
  40.  
  41. /*
  42.  * Name:    record_on_off
  43.  * Purpose: save keystrokes in keystroke buffer
  44.  * Date:    April 1, 1992
  45.  * Passed:  window:  pointer to current window
  46.  * Notes:   -1 in .next field indicates the end of a recording
  47.  *          -1 in .key field indicates the initial, unassigned macro key
  48.  *          STROKE_LIMIT+1 in .next field indicates an unused space.
  49.  */
  50. int  record_on_off( WINDOW *window )
  51. {
  52. register int next;
  53. int  prev;
  54. int  line;
  55. int  key;
  56. int  func;
  57. char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute  */
  58.  
  59.    mode.record = !mode.record;
  60.    if (mode.record == TRUE) {
  61.       line = window->bottom_line;
  62.       show_avail_strokes( );
  63.       save_screen_line( 0, line, line_buff );
  64.       /*
  65.        * press key that will play back recording
  66.        */
  67.       set_prompt( main11, line );
  68.  
  69.       /*
  70.        * get the candidate macro key and look up the function assigned to it.
  71.        */
  72.       key = getkey( );
  73.       func = getfunc( key );
  74.  
  75.       /*
  76.        * the key must be an unused, recognized function key or a function
  77.        *  key assigned to a previously defined macro.  we also need room
  78.        *  in the macro structure.
  79.        */
  80.       if (key <= 256 || (func != 0 && func != PlayBack)) {
  81.          /*
  82.           * cannot assign a recording to this key
  83.           */
  84.          error( WARNING, line, main12 );
  85.          mode.record = FALSE;
  86.       } else if (g_status.stroke_count == 0) {
  87.          /*
  88.           * no more room in recording buffer
  89.           */
  90.          error( WARNING, line, main13 );
  91.          mode.record = FALSE;
  92.       } else {
  93.  
  94.          /*
  95.           * everything is everything so far, just check for a prev macro
  96.           */
  97.          prev = OK;
  98.          if (func == PlayBack) {
  99.             /*
  100.              * overwrite recording (y/n)?
  101.              */
  102.             set_prompt( main14, line );
  103.             if (get_yn( ) == A_NO) {
  104.                prev = ERROR;
  105.                mode.record = FALSE;
  106.             }
  107.          }
  108.          if (prev == OK) {
  109.             g_status.recording_key = key;
  110.             next = macro.first_stroke[key-256];
  111.  
  112.             /*
  113.              * if key has already been assigned to a macro, clear macro def.
  114.              */
  115.             if (next != STROKE_LIMIT+1) {
  116.                do {
  117.                   prev = next;
  118.                   next = macro.strokes[next].next;
  119.                   macro.strokes[prev].key  = MAX_KEYS+1;
  120.                   macro.strokes[prev].next = STROKE_LIMIT+1;
  121.                   ++g_status.stroke_count;
  122.                } while (next != -1);
  123.                show_avail_strokes( );
  124.             }
  125.  
  126.             /*
  127.              * find the first open space and initialize
  128.              */
  129.             for (next=0; macro.strokes[next].next != STROKE_LIMIT+1;)
  130.                next++;
  131.             macro.first_stroke[key-256] = next;
  132.             macro.strokes[next].key  = -1;
  133.             macro.strokes[next].next = -1;
  134.             key_func.key[key-256] = PlayBack;
  135.             /*
  136.              * recording
  137.              */
  138.             s_output( main15, g_display.mode_line, 22,
  139.                       g_display.mode_color | 0x80 );
  140.          }
  141.       }
  142.       restore_screen_line( 0, line, line_buff );
  143.    }
  144.  
  145.    /*
  146.     * the flashing "Recording" and the stroke count write over the modes.
  147.     *  when we get thru defining a macro, redisplay the modes.
  148.     */
  149.    if (mode.record == FALSE) {
  150.       memset( line_buff, ' ', 36 );
  151.       line_buff[36] = '\0';
  152.       s_output( line_buff, g_display.mode_line, 22, g_display.mode_color );
  153.       show_tab_modes( );
  154.       show_indent_mode( );
  155.       show_sync_mode( );
  156.       show_search_case( );
  157.       show_wordwrap_mode( );
  158.  
  159.       /*
  160.        * let's look at the macro.  if the first .key of the macro is
  161.        *  still -1, which is the initial unassigned key in a macro, reset
  162.        *  the macro so other keys may be assigned to this node.
  163.        */
  164.       key = g_status.recording_key;
  165.       if (key != 0) {
  166.          next = macro.first_stroke[key-256];
  167.          if (macro.strokes[next].key == -1) {
  168.             macro.strokes[next].key  = MAX_KEYS+1;
  169.             macro.strokes[next].next = STROKE_LIMIT+1;
  170.             macro.first_stroke[key-256] = STROKE_LIMIT+1;
  171.             if (getfunc( key ) == PlayBack)
  172.                key_func.key[key-256] = 0;
  173.          }
  174.       }
  175.       g_status.recording_key = 0;
  176.    }
  177.    return( OK );
  178. }
  179.  
  180.  
  181. /*
  182.  * Name:    record_keys
  183.  * Purpose: save keystrokes in keystroke buffer
  184.  * Date:    April 1, 1992
  185.  * Passed:  line: line to display prompts
  186.  * Notes:   -1 in .next field indicates the end of a recording
  187.  *          STROKE_LIMIT+1 in .next field indicates an unused space.
  188.  */
  189. void record_keys( int line )
  190. {
  191. register int next;
  192. register int prev;
  193. int  key;
  194. int  func;
  195.  
  196.    if (mode.record == TRUE) {
  197.       if (g_status.stroke_count == 0)
  198.          /*
  199.           * no more room in recording buffer
  200.           */
  201.          error( WARNING, line, main13 );
  202.       else {
  203.          key = g_status.key_pressed;
  204.          func = getfunc( key );
  205.          if (func != RecordMacro && func != SaveMacro && func != LoadMacro &&
  206.              func != ClearAllMacros) {
  207.  
  208.             /*
  209.              * a -1 in the next field marks the end of the keystroke recording.
  210.              */
  211.             next = macro.first_stroke[g_status.recording_key - 256];
  212.             if (macro.strokes[next].next != STROKE_LIMIT+1) {
  213.                while (macro.strokes[next].next != -1)
  214.                   next = macro.strokes[next].next;
  215.             }
  216.             prev = next;
  217.  
  218.             /*
  219.              * now find an open space to record the current key.
  220.              */
  221.             if (macro.strokes[next].key != -1) {
  222.                for (; next < STROKE_LIMIT &&
  223.                             macro.strokes[next].next != STROKE_LIMIT+1;)
  224.                   next++;
  225.                if (next == STROKE_LIMIT) {
  226.                   for (next=0; next < prev &&
  227.                                macro.strokes[next].next != STROKE_LIMIT+1;)
  228.                      next++;
  229.                }
  230.             }
  231.             if (next == prev && macro.strokes[prev].key != -1)
  232.                /*
  233.                 * no more room in recording buffer
  234.                 */
  235.                error( WARNING, line, main13 );
  236.             else {
  237.             /*
  238.              * next == prev if we are recording the initial macro node.
  239.              */
  240.                macro.strokes[prev].next = next;
  241.                macro.strokes[next].next = -1;
  242.                macro.strokes[next].key  = key;
  243.                g_status.stroke_count--;
  244.                show_avail_strokes( );
  245.             }
  246.          }
  247.       }
  248.    }
  249. }
  250.  
  251.  
  252. /*
  253.  * Name:    show_avail_strokes
  254.  * Purpose: show available free key strokes in lite bar at bottom of screen
  255.  * Date:    April 1, 1992
  256.  */
  257. void show_avail_strokes( void )
  258. {
  259. char strokes[MAX_COLS];
  260.  
  261.    s_output( main18, g_display.mode_line, 33, g_display.mode_color );
  262.    itoa( g_status.stroke_count, strokes, 10 );
  263.    s_output( "      ", g_display.mode_line, 51, g_display.mode_color );
  264.    s_output( strokes, g_display.mode_line, 51, g_display.mode_color );
  265. }
  266.  
  267.  
  268. /*
  269.  * Name:    save_strokes
  270.  * Purpose: save strokes to a file
  271.  * Date:    April 1, 1992
  272.  * Passed:  window:  pointer to current window
  273.  */
  274. int  save_strokes( WINDOW *window )
  275. {
  276. FILE *fp;                       /* file to be written */
  277. char name[MAX_COLS+2];          /* file name */
  278. char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute  */
  279. register int rc;
  280. int  prompt_line;
  281. int  fattr;
  282.  
  283.    name[0] = '\0';
  284.    prompt_line = window->bottom_line;
  285.    save_screen_line( 0, prompt_line, line_buff );
  286.    /*
  287.     * name for macro file
  288.     */
  289.    if ((rc = get_name( main19, prompt_line, name,
  290.                  g_display.message_color )) == OK  &&  *name != '\0') {
  291.  
  292.       /*
  293.        * make sure it is OK to overwrite any existing file
  294.        */
  295.       rc = get_fattr( name, &fattr );
  296.       if (rc == OK) {
  297.          /*
  298.           * overwrite existing file
  299.           */
  300.          set_prompt( main20, prompt_line );
  301.          if (get_yn( ) != A_YES  ||  change_mode( name, prompt_line ) == ERROR)
  302.             rc = ERROR;
  303.       }
  304.       if (rc != ERROR) {
  305.          if ((fp = fopen( name, "wb" )) != NULL) {
  306.             fwrite( ¯o.first_stroke[0], sizeof(int), MAX_KEYS, fp );
  307.             fwrite( ¯o.strokes[0], sizeof(STROKES), STROKE_LIMIT, fp );
  308.             fclose( fp );
  309.          }
  310.       }
  311.    }
  312.    restore_screen_line( 0, prompt_line, line_buff );
  313.    return( OK );
  314. }
  315.  
  316.  
  317. /*
  318.  * Name:    load_strokes
  319.  * Purpose: load strokes from a file
  320.  * Date:    April 1, 1992
  321.  * Passed:  window:  pointer to current window
  322.  * Notes:   show the user a file pick list.  I can never remember macro
  323.  *           file names or the directory in which they hide.  might as well
  324.  *           give the user a file pick list.
  325.  */
  326. int  load_strokes( WINDOW *window )
  327. {
  328. register FILE *fp;      /* file to be read */
  329. char dname[MAX_COLS];   /* directory search pattern */
  330. char stem[MAX_COLS];    /* directory stem */
  331. register int rc;
  332.  
  333.    dname[0] = '\0';
  334.    /*
  335.     * search path for macro file
  336.     */
  337.    if (get_name( main21, window->bottom_line, dname,
  338.                  g_display.message_color ) == OK  &&  *dname != '\0') {
  339.       if (validate_path( dname, stem ) == OK) {
  340.          rc = list_and_pick( dname, stem, window );
  341.  
  342.          /*
  343.           * if everything is everything, load in the file selected by user.
  344.           */
  345.          if (rc == OK) {
  346.             if ((fp = fopen( dname, "rb" )) != NULL && ceh.flag != ERROR) {
  347.                fwrite( ¯o.first_stroke[0], sizeof(int), MAX_KEYS, fp );
  348.                fwrite( ¯o.strokes[0], sizeof(STROKES), STROKE_LIMIT, fp );
  349.                fclose( fp );
  350.             }
  351.             if (ceh.flag == OK)
  352.                connect_macros( );
  353.          }
  354.       } else
  355.          /*
  356.           * invalid path or file name
  357.           */
  358.          error( WARNING, window->bottom_line, main22 );
  359.    }
  360.    return( OK );
  361. }
  362.  
  363.  
  364. /*
  365.  * Name:    clear_macro
  366.  * Purpose: reset all macro buffers, pointers, functions.
  367.  * Date:    April 1, 1992
  368.  * Notes:   reset the available macro stroke count.  reset all fields in
  369.  *           macro structure.  clear any keys assigned to macros in the
  370.  *           function assignment array.
  371.  */
  372. int  clear_macros( WINDOW *arg_filler )
  373. {
  374. register int i;
  375.  
  376.    g_status.stroke_count = STROKE_LIMIT;
  377.    for (i=0; i<STROKE_LIMIT; i++) {
  378.       macro.strokes[i].next = STROKE_LIMIT+1;
  379.       macro.strokes[i].key  = MAX_KEYS+1;
  380.    }
  381.    for (i=0; i<MAX_KEYS; i++) {
  382.       macro.first_stroke[i] = STROKE_LIMIT+1;
  383.       if (key_func.key[i] == PlayBack)
  384.          key_func.key[i] = 0;
  385.    }
  386.    return( OK );
  387. }
  388.  
  389.  
  390. /*
  391.  * Name:    connect_macros
  392.  * Purpose: hook up all (if any) macros to the function key definition table
  393.  * Date:    April 1, 1992
  394.  * Notes:   we need to connect all macro definitions to the key definition
  395.  *           table in the startup routine or when we read in a new macro
  396.  *           definition file.  the predefined func assignments take
  397.  *           precedence over macro definitions.
  398.  */
  399. void connect_macros( void )
  400. {
  401. register int i;
  402.  
  403.    /*
  404.     * reset the key function assignment array.  initially, no keys may be
  405.     *  assigned to a macro.
  406.     */
  407.    for (i=0; i<MAX_KEYS; i++)
  408.       if (key_func.key[i] == PlayBack)
  409.          key_func.key[i] = 0;
  410.  
  411.    /*
  412.     * now, find out how many free keystrokes are in the macro structure.
  413.     */
  414.    g_status.stroke_count = 0;
  415.    for (i=0; i<STROKE_LIMIT; i++)
  416.       if (macro.strokes[i].next == STROKE_LIMIT+1)
  417.          ++g_status.stroke_count;
  418.  
  419.    /*
  420.     * go thru the first stroke list to see if any key has been assigned to
  421.     *  a macro and connect the macro def to the key.  predefined function
  422.     *  assignments take precedence over macros.
  423.     */
  424.    for (i=0; i<MAX_KEYS; i++) {
  425.       if (macro.first_stroke[i] != STROKE_LIMIT+1)
  426.          if (key_func.key[i] == 0)
  427.             key_func.key[i] = PlayBack;
  428.    }
  429. }
  430.  
  431.  
  432. /*
  433.  *              keystroke play back functions
  434.  */
  435.  
  436.  
  437. /*
  438.  * Name:    play_back
  439.  * Purpose: play back a series of keystrokes assigned to key
  440.  * Date:    April 1, 1992
  441.  * Notes:   go thru the macro key list playing back the recorded keystrokes.
  442.  *          to let macros call other macros, we have to 1) save the next
  443.  *           keystroke of the current macro in a stack, 2) execute the
  444.  *           the called macro, 3) pop the key that saved by the calling
  445.  *           macro, 4) continue executing the macro, beginning with the
  446.  *           key we just popped.
  447.  *          use a local stack to store keys.  currently, there is room
  448.  *           for 256 keys -- should be enough room for most purposes.
  449.  */
  450. int  play_back( WINDOW *window )
  451. {
  452. int  key;
  453. int  rc = OK;
  454. int  popped;            /* flag is set when macro is popped */
  455.  
  456.    /*
  457.     * if we are recording a macro, let's just return if we do a recursive
  458.     *  definition.  Otherwise, we end up executing our recursive macro
  459.     *  while we are defining it.
  460.     */
  461.    if (mode.record == TRUE && g_status.key_pressed == g_status.recording_key)
  462.       rc = ERROR;
  463.    else {
  464.  
  465.       /*
  466.        * set the global macro flags, so other routines will know
  467.        *  if a macro is executing.
  468.        * set the stack_pointer to "empty" or -1.  initialize the popped
  469.        *  flag to FALSE being that we haven't popped any thing off the stack,
  470.        *  yet.
  471.        */
  472.       g_status.macro_executing = TRUE;
  473.       g_status.mstack_pointer  = -1;
  474.       popped = FALSE;
  475.       rc = OK;
  476.       while (rc == OK) {
  477.  
  478.          /*
  479.           * the first time thru the loop, popped is FALSE.  some lint
  480.           *  utilities may complain about key being used but not defined.
  481.           */
  482.          if (popped == FALSE) {
  483.  
  484.             /*
  485.              * find the first keystroke in the macro.  when we pop the stack,
  486.              *  all this stuff is reset by the pop -- do not reset it again.
  487.              */
  488.             g_status.macro_next = macro.first_stroke[g_status.key_pressed-256];
  489.             g_status.current_macro = g_status.key_pressed;
  490.             key = macro.strokes[g_status.macro_next].key;
  491.          }
  492.          popped = FALSE;
  493.          if (key != MAX_KEYS+1  &&  key != -1) {
  494.             do {
  495.  
  496.                /*
  497.                 * set up all editor variables as if we were entering
  498.                 *  keys from the keyboard.
  499.                 */
  500.                window = g_status.current_window;
  501.                display_dirty_windows( window );
  502.                ceh.flag = OK;
  503.                g_status.key_pressed = macro.strokes[g_status.macro_next].key;
  504.                g_status.command = getfunc( g_status.key_pressed );
  505.                if (g_status.wrapped  ||  g_status.key_pending) {
  506.                   g_status.key_pending = FALSE;
  507.                   g_status.wrapped = FALSE;
  508.                   show_search_message( CLR_SEARCH, g_display.mode_color );
  509.                }
  510.  
  511.                /*
  512.                 * while there are no errors or Control-Breaks, let's keep on
  513.                 *  executing a macro.  g_status.control_break is a global
  514.                 *  editor flag that is set in our Control-Break interrupt
  515.                 *  handler routine.
  516.                 */
  517.                if (g_status.control_break == TRUE) {
  518.                   rc = ERROR;
  519.                   break;
  520.                }
  521.  
  522.                /*
  523.                 * we haven't called any editor function yet.  we need
  524.                 *  to look at the editor command that is to be executed.
  525.                 *  if the command is PlayBack, we need to break out of
  526.                 *  this inner do loop and start executing the macro
  527.                 *  from the beginning (the outer do loop).
  528.                 *
  529.                 * if we don't break out now from a recursive macro, we will
  530.                 *  recursively call PlayBack and we will likely overflow
  531.                 *  the main (as opposed to the macro_stack) stack.
  532.                 */
  533.                if (g_status.command == PlayBack) {
  534.  
  535.                   /*
  536.                    * recursive macros are handled differently from
  537.                    *  macros that call other macros.
  538.                    * recursive macros - break out of this inner loop
  539.                    *  and begin executing the macro from the beg of macro.
  540.                    * standard macros - save the next instruction of this
  541.                    *  macro on the stack and begin executing the called macro.
  542.                    */
  543.                   if (g_status.current_macro != g_status.key_pressed) {
  544.                      if (push_macro_stack(
  545.                                    macro.strokes[g_status.macro_next].next )
  546.                                    != OK) {
  547.                         error( WARNING, window->bottom_line, ed16 );
  548.                         rc = ERROR;
  549.                      }
  550.                      g_status.macro_next =
  551.                                 macro.first_stroke[g_status.key_pressed-256];
  552.                      g_status.current_macro = g_status.key_pressed;
  553.                      key = macro.strokes[g_status.macro_next].key;
  554.  
  555.                      /*
  556.                       * execute called macro at beginning of this do loop.
  557.                       */
  558.                      continue;
  559.                   } else
  560.  
  561.                      /*
  562.                       * recursive macro - break out of this inner loop
  563.                       *  or else we may overflow the stack(s).
  564.                       */
  565.                      break;
  566.                }
  567.  
  568.  
  569.                /*
  570.                 * just as we assert before the main editor routine, let's
  571.                 *  assert in the macro function to make sure everything
  572.                 *  is everything.
  573.                 */
  574. #if defined(  __MSC__ )
  575.                assert( window != NULL );
  576.                assert( window->file_info != NULL );
  577.                assert( window->file_info->line_list != NULL );
  578.                assert( window->file_info->line_list_end != NULL );
  579.                assert( window->file_info->line_list_end->len == EOF );
  580.                assert( window->visible == TRUE );
  581.                assert( window->rline >= 0 );
  582.                assert( window->rline <= window->file_info->length + 1 );
  583.                assert( window->rcol >= 0 );
  584.                assert( window->rcol < MAX_LINE_LENGTH );
  585.                assert( window->ccol >= window->start_col );
  586.                assert( window->ccol <= window->end_col );
  587.                assert( window->bcol >= 0 );
  588.                assert( window->bcol < MAX_LINE_LENGTH );
  589.                assert( window->bcol == window->rcol-(window->ccol - window->start_col) );
  590.                assert( window->start_col >= 0 );
  591.                assert( window->start_col < window->end_col );
  592.                assert( window->end_col < g_display.ncols );
  593.                assert( window->cline >= window->top_line );
  594.                assert( window->cline <= window->bottom_line );
  595.                assert( window->top_line > 0 );
  596.                assert( window->top_line <= window->bottom_line );
  597.                assert( window->bottom_line < MAX_LINES );
  598.                assert( window->bin_offset >= 0 );
  599.                if (window->ll->next == NULL)
  600.                   assert( window->ll->len == EOF );
  601.                else
  602.                   assert( window->ll->len >= 0 );
  603.                assert( window->ll->len <  MAX_LINE_LENGTH );
  604. #endif
  605.  
  606.  
  607.                if (g_status.command >= 0 && g_status.command < NUM_FUNCS)
  608.                    rc = (*do_it[g_status.command])( window );
  609.                g_status.macro_next =
  610.                           macro.strokes[g_status.macro_next].next;
  611.             } while (rc == OK  &&  g_status.macro_next != -1);
  612.  
  613.             /*
  614.              * if we have come the end of a macro definition and there
  615.              *  are no keys saved on the stack, we have finished our
  616.              *  macro.  get out.
  617.              */
  618.             if (g_status.macro_next == -1 && g_status.mstack_pointer < 0)
  619.                rc = ERROR;
  620.             else if (rc != ERROR  &&  g_status.mstack_pointer >= 0) {
  621.  
  622.                /*
  623.                 * if this is a recursive macro, don't pop the stack
  624.                 *  because we didn't push.
  625.                 * for a standard macro, get back the next key in the
  626.                 *  calling macro.
  627.                 */
  628.                if (g_status.current_macro != g_status.key_pressed) {
  629.                   if (pop_macro_stack( &g_status.macro_next ) != OK) {
  630.                      error( WARNING, window->bottom_line, ed17 );
  631.                      rc = ERROR;
  632.                   } else {
  633.                      popped = TRUE;
  634.                      key = macro.strokes[g_status.macro_next].key;
  635.                   }
  636.                }
  637.             }
  638.          }
  639.       }
  640.       g_status.macro_executing = FALSE;
  641.    }
  642.    return( OK );
  643. }
  644.  
  645.  
  646. /*
  647.  * Name:    push_macro_stack
  648.  * Purpose: push the next key in a currently executing macro on local stack
  649.  * Date:    October 31, 1992
  650.  * Notes:   finally got tired of letting macros only "jump" and not call
  651.  *           other macros.
  652.  *          the first time in, stack_pointer is -1.
  653.  */
  654. int  push_macro_stack( int key )
  655. {
  656.    /*
  657.     * first, make sure we have room to push the key.
  658.     */
  659.    if (g_status.mstack_pointer+1 < MAX_KEYS) {
  660.  
  661.       /*
  662.        * increment the stack pointer and store the pointer to the next key
  663.        *  of the currently executing macro.  store the currently executing
  664.        *  macro, too.
  665.        */
  666.       ++g_status.mstack_pointer;
  667.       macro_stack[g_status.mstack_pointer].key = key;
  668.       macro_stack[g_status.mstack_pointer].macro = g_status.current_macro;
  669.       return( OK );
  670.    } else
  671.       return( STACK_OVERFLOW );
  672. }
  673.  
  674.  
  675. /*
  676.  * Name:    pop_macro_stack
  677.  * Purpose: pop currently executing macro on local stack
  678.  * Date:    October 31, 1992
  679.  * Notes:   finally got tired of letting macros only "jump" and not "call"
  680.  *           other macros.
  681.  *          pop the macro stack.  stack pointer is pointing to last key saved
  682.  *           on stack.
  683.  */
  684. int  pop_macro_stack( int *key )
  685. {
  686.  
  687.    /*
  688.     * before we pop the stack, make sure there is something in the stack.
  689.     */
  690.    if (g_status.mstack_pointer >= 0) {
  691.  
  692.       /*
  693.        * pop the pointer to the next key and the current macro, then
  694.        *  decrement the stack_pointer.
  695.        */
  696.       *key = macro_stack[g_status.mstack_pointer].key;
  697.       g_status.current_macro = macro_stack[g_status.mstack_pointer].macro;
  698.       --g_status.mstack_pointer;
  699.       return( OK );
  700.    } else
  701.       return( STACK_UNDERFLOW );
  702. }
  703.  
  704.  
  705. /*
  706.  * Name:    Pause
  707.  * Purpose: Enter pause state for macros
  708.  * Date:    June 5, 1992
  709.  * Passed:  arg_filler:  argument to satify function prototype
  710.  * Returns: ERROR if the ESC key was pressed, OK otherwise.
  711.  * Notes:   this little function is quite useful in macro definitions.  if
  712.  *          it is called near the beginning of a macro, the user may decide
  713.  *          whether or not to stop the macro.
  714.  */
  715. int  pause( WINDOW *arg_filler )
  716. {
  717. int  c;
  718.  
  719.    /*
  720.     * tell user we are paused.  the '|  0x80' turns on the blink attribute
  721.     */
  722.    s_output( paused1, g_display.mode_line, 23, g_display.mode_color | 0x80 );
  723.    s_output( paused2, g_display.mode_line, 23+strlen( paused1 ),
  724.              g_display.mode_color );
  725.  
  726.    /*
  727.     * get the user's response and restore the mode line.
  728.     */
  729.    c = getkey( );
  730.    show_modes( );
  731.    if (mode.record == TRUE) {
  732.       /*
  733.        * if recording a macro, show recording message
  734.        */
  735.       s_output( main15, g_display.mode_line, 23, g_display.mode_color | 0x80 );
  736.       show_avail_strokes( );
  737.    }
  738.    return( c == ESC ? ERROR : OK );
  739. }
  740.